<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <script>

        // Thunkify 模块
        // 生产环境的转换器，建议使用 Thunkify 模块。
        function thunkify(fn) { //fn参数为函数 ->fn(a, b, callback)  -----1-1
            return function () {// ft函数执行时调用 ->ft(1, 2, 'task1')  -----3-1
                let ctx = this;
                let args = [...arguments]; // args-> [1, 2, 'task1']
                return function (print) { // ft(1, 2, 'task1')(print) ；print -> print == console.log -----3-2
                    let called;
                    if (args.length >= 4) { 
                        let len=args.length;
                        args = args.slice(0,args.length-1);
                    }// 把上次的加的callback函数删除
                    args.push( // [1, 0, 'task1'].push(就是callback函数)-->[1, 2, 'task1',callback函数]   -----4
                        function () {  //    这里的function 就是callback函数； callback函数 这个时候才被确定下来并且放入args数组
                            if (called)//-----7
                            {
                                return;
                            }
                            called = true;
                            // print.apply(null, arguments); // null,'task1', 3 
                            let [sum, id] = [...arguments];// arguments ->> sum, id
                            print.call(null, id, sum); // null,'task1', 3     

                        }
                    );

                    try {
                        // fn.apply(ctx, args); //fn(ctx,1, 2, 'task1',callback=函数)
                        fn.call(ctx, ...args); //fn(ctx,1, 2, 'task1',callback=函数) -----5
                    } catch (err) {
                        //print(err);
                    }
                }
            }
        };
        function fn(a, b, id, callback) { //fn(ctx,1, 2,callback=函数)
            let sum = a + b;
            // alert(this);
            callback(sum, id); //-----6
        }
        let ft = thunkify(fn); // -----1 函数定义
        let print = console.log.bind(console); // -----2 函数定义
        //var print = console.log;
        let myfun = ft(1, 2, 'task1');// thunkify(fn)(1, 0, 'task1')(print)  -----3-1，3-2 函数调用

        // myfun(print);
        // myfun(print);

        const mygenerator = function* () {
            yield ft(1, 2, 'task1')(print);// thunkify(fn)(1, 0, 'task1')(print)  -----3-1，3-2 函数调用
            yield ft(2, 3, 'task2')(print);
            yield ft(3, 4, 'task3')(print);
            yield ft(4, 5, 'task4')(print);
        }

        console.log("start!")
        let myiterator = mygenerator();
        myiterator.next();//task1
        myiterator.next();//task2
        myiterator.next();//task3
        myiterator.next();//task4
        console.log("over!")


        // const person = function () {
        //     return function getpersonsex() {
        //         return this.sex;
        //     }
        // }

        // let user = { "name": "szq", age: 11 };
        // Reflect.setPrototypeOf(user, person);
        // user.sex = "this_man";
        // user.prototype.sex = "parent_man";

        // console.log(user);
        // console.log("person:" + person().call(user));



        // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // // JavaScript 语言的 Thunk 函数
        // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // // JavaScript 语言是传值调用，它的 Thunk 函数含义有所不同。
        // // 在 JavaScript 语言中，Thunk 函数替换的不是表达式，而是多参数函数，
        // // 将其替换成一个只接受回调函数作为参数的单参数函数。
        // const Thunk = function (fn) {
        //     return function (...args) {
        //         return function (callback) {
        //             return fn.call(this, ...args, callback);// fn =>f(a, cb);a==args==1,cb==callback==console.log ,this=>window
        //         }
        //     };
        // };
        // function f(a, cb) {
        //     cb(a);
        // }
        // const ft = Thunk(f);

        // ft(1)(console.log) // ft=>Thunk(f)=>执行function (fn)=>闭包中得到 fn=f =>并且返回 function (...args)函数
        //                    // ft(1)=> 闭包中得到args=1； 并且执行function (...args)函数 =>返回 function (callback)函数
        //                    // ft(1)(console.log) => 闭包中得到callback=console.log； 并且执行function (callback)函数
        //                    //=>执行 fn.call(this, ...args, callback)函数，== f(this,1,console.log)==console.log(1)
        //                 //总结：Thunk函数书写的过程分别是：定义要执行的函数fn，要执行的参数args，要执行的回调函数callback ，
        //                 //     最后call：其实就是真正执行函数f(a,ab) 



    </script>
</head>

<body>

</body>

</html>